﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using Xwltz.Framework.Helper;

namespace Xwltz.Framework.Database
{
    /// <summary>
    /// 数据库帮助类
    /// </summary>
    public class DataBaseHelper
    {
        /// <summary>
        /// 获取实体对应的表名
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public string GetTableName(Type type)
        {
            var customAttributes = type.GetCustomAttributes(typeof(XTableAttribute), false);
            return customAttributes.Length <= 0 ? type.Name : ((XTableAttribute)customAttributes[0]).Name;
        }

        /// <summary>
        /// 标记属性不是数据库字段
        /// </summary>
        public class XNotMappedAttribute : Attribute
        {

        }

        /// <summary>
        /// 标记实体对应的数据库表名
        /// </summary>
        public class XTableAttribute : Attribute
        {
            public string Name
            {
                get;
            }

            public XTableAttribute(string name)
            {
                Name = name;
            }
        }

        /// <summary>
        /// 标记该属性为主键
        /// </summary>
        public class XKeyAttribute : Attribute
        {

        }

        /// <summary>
        /// 标记该属性为自增列
        /// </summary>
        public class XIdentityKeyAttribute : Attribute
        {

        }

        /// <summary>
        /// 转换成Int32类型
        /// </summary>
        public static int ExecToInt32(DbDataReader reader, string columnName)
        {
            return reader[columnName] == DBNull.Value ? 0 : Convert.ToInt32(reader[columnName]);
        }
        /// <summary>
        /// 转换成String类型
        /// </summary>
        public static string ExecToString(DbDataReader reader, string columnName)
        {
            return reader[columnName] == DBNull.Value ? "" : reader[columnName].ToString();
        }
        /// <summary>
        /// 转换成DateTime类型
        /// </summary>
        public static DateTime ExecToDateTime(DbDataReader reader, string columnName)
        {
            return reader[columnName] == DBNull.Value ? DateTime.MinValue : Convert.ToDateTime(reader[columnName]);
        }
        /// <summary>
        /// 转换成Double类型
        /// </summary>
        public static Double ExecToDateDouble(DbDataReader reader, string columnName)
        {
            return reader[columnName] == DBNull.Value ? 0 : Convert.ToDouble(reader[columnName]);
        }
        /// <summary>
        /// 转换成Decimal类型
        /// </summary>
        public static decimal ExecToDecimal(DbDataReader reader, string columnName)
        {
            return reader[columnName] == DBNull.Value ? 0 : Convert.ToDecimal(reader[columnName]);
        }

        /// <summary>
        /// 转换成Decimal类型
        /// </summary>
        public static bool ExecToBoolean(DbDataReader reader, string columnName)
        {
            return reader[columnName] == DBNull.Value ? false : Convert.ToBoolean(reader[columnName]);
        }

        /// <summary>
        /// DataTable 转 List
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="table"></param>
        /// <returns></returns>
        public static List<TModel> TableToList<TModel>(DataTable table) where TModel : new()
        {
            var typeFromHandle = typeof(TModel);
            var properties = typeFromHandle.GetProperties();
            var list = new List<TModel>();
            foreach (DataRow dataRow in table.Rows)
            {
                var tModel = (default(TModel) == null) ? Activator.CreateInstance<TModel>() : default(TModel);
                var enumerator2 = table.Columns.GetEnumerator();
                try
                {
                    DataColumn col;
                    while (enumerator2.MoveNext())
                    {
                        col = (DataColumn)enumerator2.Current;
                        var propertyInfo = properties.FirstOrDefault(a => col != null && a.Name.Equals(col.ColumnName));
                        if (propertyInfo == null ||
                            propertyInfo.GetCustomAttributes(typeof(XNotMappedAttribute), false).Length > 0) continue;
                        if (col != null)
                        {
                            var obj = dataRow[col.ColumnName];
                            if (obj == DBNull.Value) continue;
                        }
                        if (propertyInfo.PropertyType.Name.Equals("Boolean"))
                        {
                            propertyInfo.SetValue(tModel, col != null && dataRow[col.ColumnName].ToString().ToBool(), null);
                        }
                        else if (propertyInfo.PropertyType.Name.Equals("Int32"))
                        {
                            if (col != null) propertyInfo.SetValue(tModel, dataRow[col.ColumnName].ToString().ToInt(), null);
                        }
                        else
                        {
                            if (col != null) propertyInfo.SetValue(tModel, dataRow[col.ColumnName], null);
                        }
                    }
                }
                finally
                {
                    var disposable = enumerator2 as IDisposable;
                    disposable?.Dispose();
                }
                list.Add(tModel);
            }
            return list;
        }

        /// <summary>
        /// DataRow 转 Model
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="row"></param>
        /// <returns></returns>
        public static TModel RowToModel<TModel>(DataRow row) where TModel : new()
        {
            var typeFromHandle = typeof(TModel);
            var properties = typeFromHandle.GetProperties();
            var tModel = (default(TModel) == null) ? Activator.CreateInstance<TModel>() : default(TModel);
            var array = properties;
            foreach (var propertyInfo in array)
            {
                if (propertyInfo == null ||
                    propertyInfo.GetCustomAttributes(typeof(XNotMappedAttribute), false).Length > 0) continue;
                var obj = row[propertyInfo.Name];
                if (obj == DBNull.Value) continue;
                if (propertyInfo.PropertyType.Name.Equals("Boolean"))
                {
                    propertyInfo.SetValue(tModel, row[propertyInfo.Name].ToString().ToBool(), null);
                }
                else if (propertyInfo.PropertyType.Name.Equals("Int32"))
                {
                    propertyInfo.SetValue(tModel, row[propertyInfo.Name].ToString().ToInt(), null);
                }
                else
                {
                    propertyInfo.SetValue(tModel, row[propertyInfo.Name], null);
                }
            }
            return tModel;
        }
    }

    /// <summary>
    /// 表字段信息模型
    /// </summary>
    public class TableColumns
    {
        /// <summary>
        /// 字段名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 字段类型
        /// </summary>
        public string Type { get; set; }
        /// <summary>
        /// 字段大小
        /// </summary>
        public string Size { get; set; }
        /// <summary>
        /// 是否为主键
        /// </summary>
        public string PrimaryKey { get; set; }
        /// <summary>
        /// 是否为自增列
        /// </summary>
        public string Identity { get; set; }
        /// <summary>
        /// 是否为必填
        /// </summary>
        public string IsNull { get; set; }
        /// <summary>
        /// 字段注释
        /// </summary>
        public string Remark { get; set; }
    }
}